package com.zomiot.portal.user.service;

import cn.dev33.satoken.stp.StpUtil;
import com.zomiot.portal.auth.constant.UserState;
import com.zomiot.portal.common.exception.BusinessException;
import com.zomiot.portal.user.dto.LoginRequest;
import com.zomiot.portal.user.dto.RegisterRequest;
import com.zomiot.portal.user.dto.UserInfoVO;
import com.zomiot.portal.user.entity.UserPO;
import com.zomiot.portal.user.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 用户业务逻辑层
 *
 * @author Joash_Yi
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;

    /**
     * 用户注册
     *
     * @param request 注册请求
     * @return 注册成功的用户信息
     */
    @Transactional(rollbackFor = Exception.class)
    public UserInfoVO register(RegisterRequest request) {
        log.info("用户注册：username={}", request.getUsername());

        // 1. 检查用户名是否已存在
        if (userMapper.countByUsername(request.getUsername()) > 0) {
            throw new BusinessException("用户名已存在");
        }

        // 2. 检查手机号是否已存在（如果提供了手机号）
        if (request.getTelephone() != null &&
            !request.getTelephone().isBlank() &&
            userMapper.countByTelephone(request.getTelephone()) > 0) {
            throw new BusinessException("手机号已被注册");
        }

        // 3. 检查邮箱是否已存在（如果提供了邮箱）
        if (request.getEmail() != null &&
            !request.getEmail().isBlank() &&
            userMapper.countByEmail(request.getEmail()) > 0) {
            throw new BusinessException("邮箱已被注册");
        }

        // 4. 创建用户实体
        UserPO user = UserPO.builder()
                .username(request.getUsername())
                .passwordHash(passwordEncoder.encode(request.getPassword()))
                .displayName(request.getDisplayName() != null ? request.getDisplayName() : request.getUsername())
                .telephone(request.getTelephone())
                .email(request.getEmail())
                .build(); // role和state使用默认值：MEMBER和ACTIVE

        // 5. 保存到数据库
        userMapper.insert(user);

        log.info("用户注册成功：userId={}, username={}", user.getId(), user.getUsername());

        // 6. 转换为VO返回
        return convertToVO(user);
    }

    /**
     * 用户登录
     *
     * @param request 登录请求
     * @return 用户信息（包含Token）
     */
    @Transactional(rollbackFor = Exception.class)
    public UserInfoVO login(LoginRequest request) {
        log.info("用户登录：username={}", request.getUsername());

        // 1. 根据用户名查询用户
        UserPO user = userMapper.selectByUsername(request.getUsername());
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }

        // 2. 检查用户状态
        if (user.getState() == UserState.DISABLED) {
            throw new BusinessException("账号已被禁用，请联系管理员");
        }

        // 3. 验证密码
        if (!passwordEncoder.matches(request.getPassword(), user.getPasswordHash())) {
            throw new BusinessException("用户名或密码错误");
        }

        // 4. 执行Sa-Token登录
        StpUtil.login(user.getId());

        // 5. 将用户信息存入Session（关键步骤！）
        UserInfoVO userInfo = convertToVO(user);
        StpUtil.getSession().set(user.getId().toString(), userInfo);

        // 6. 更新最后登录时间
        user.setLastLoginTime(LocalDateTime.now());
        userMapper.updateById(user);

        // 7. 获取Token并设置到返回对象中
        String token = StpUtil.getTokenValue();
        userInfo.setToken(token);

        log.info("用户登录成功：userId={}, username={}", user.getId(), user.getUsername());

        return userInfo;
    }

    /**
     * 用户登出
     */
    public void logout() {
        Object loginId = StpUtil.getLoginId();
        log.info("用户登出：userId={}", loginId);
        StpUtil.logout();
    }

    /**
     * 获取当前登录用户信息
     *
     * @return 用户信息
     */
    public UserInfoVO getCurrentUser() {
        Long userId = StpUtil.getLoginIdAsLong();

        // 优先从Session中获取（性能更好）
        UserInfoVO cachedUser = (UserInfoVO) StpUtil.getSession().get(userId.toString());
        if (cachedUser != null) {
            return cachedUser;
        }

        // Session中没有则从数据库查询
        UserPO user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        return convertToVO(user);
    }

    /**
     * 根据ID获取用户信息
     *
     * @param userId 用户ID
     * @return 用户信息
     */
    public UserInfoVO getUserById(Long userId) {
        UserPO user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        return convertToVO(user);
    }

    /**
     * 实体转VO
     *
     * @param entity 用户实体
     * @return 用户VO
     */
    private UserInfoVO convertToVO(UserPO entity) {
        return UserInfoVO.builder()
                .userId(entity.getId())
                .username(entity.getUsername())
                .displayName(entity.getDisplayName())
                .telephone(entity.getTelephone())
                .email(entity.getEmail())
                .role(entity.getRole())
                .state(entity.getState())
                .createTime(entity.getCreateTime())
                .lastLoginTime(entity.getLastLoginTime())
                .build();
    }
}